<template>
  <div class="settingContainer">
    <!-- 设置选项 -->
    <div class="optionsBar">
      <div
        class="option"
        :id="currentOption === item.index ? 'currentOption' : ''"
        v-for="item in optionList"
        :key="item.index"
        @click="selectOption(item.index)"
      >
        <div>{{ item.label }}</div>
      </div>
    </div>

    <div class="divide"></div>

    <!-- 设置选项对应功能 -->
    <CurrnetComponent :index="currentOption" />
  </div>
</template>

<script lang="tsx" setup>
import { defineComponent, ref, onMounted, watch } from 'vue'
import { storeToRefs } from 'pinia'
import localforage from 'localforage'
import { ElMessage } from 'element-plus'
import 'element-plus/theme-chalk/el-message.css'
import {
  updateInfoApi,
  modifyPasswordApi,
  updateAvatarApi,
} from '@/request/api/master'
import {
  getRoleListApi,
  getPermissionsListApi,
  getRolePermissionsDetailApi,
  setRolePermissionsApi,
  getUserRolesApi,
  setUserRolesApi,
} from '@/request/api/role'
import {
  userAddApi,
  userCheckApi,
  userDeleteApi,
  userEditApi,
} from '@/request/api/permissions'
import styles from './setting.module.less'
import { useThemeStore, useUserInfoStore } from '@/features/store/store'
import LoadingClass from '@/utils/utilClass/Loading'
import { fetchOriginFile } from '@/utils/func'
import { sourceUrl } from '@/config/baseConfig'

// 设置选项列表
const optionList: { index: number; label: string }[] = [
  { index: 1, label: '个人信息' },
  { index: 2, label: '密码' },
  { index: 3, label: '主题' },
  { index: 4, label: '权限控制测试' },
]
// 当前设置选项
const currentOption = ref<number>(4)
// 选择设置选项
const selectOption = (val: number) => (currentOption.value = val)

//
// 用户当前需要展现的部分
const CurrnetComponent = defineComponent({
  props: {
    index: { type: Number, default: '' },
  },
  setup(props) {
    //组件列表
    const ComponentObj: { [key: number]: JSX.Element } = {
      1: <UserInfo />,
      2: <UserPassword />,
      3: <CustomTheme />,
      4: <AuthorityControl />,
    }

    return () => <> {ComponentObj[props.index]}</>
  },
})

//
// 用户信息设置部分
const UserInfo = defineComponent({
  setup() {
    const { buttonColor } = storeToRefs(useThemeStore())
    const {
      avatar: a,
      nickname: n,
      description: d,
      email: e,
    } = storeToRefs(useUserInfoStore())

    const avatar = ref<string>('')
    const nickname = ref<string>(n.value)
    const description = ref<string>(d.value)
    const email = ref<string>(e.value)

    onMounted(() => {
      // 从本地仓库获取头像并设置头像地址
      // @ts-ignore
      localforage.getItem('userInfoCache', (err, value) => {
        avatar.value = (value as userInfoCacheItf).avatar.path
      })
    })

    watch(
      () => a.value,
      () => (avatar.value = sourceUrl + a.value)
    )

    const ClassLoading = new LoadingClass()

    // 更新个人信息
    const updateInfo = async () => {
      const data = {
        nickname: nickname.value.trim(),
        description: description.value.trim(),
        email: email.value?.trim(),
      }
      ClassLoading.loading.value = true
      const res = await updateInfoApi(data)
      ClassLoading.loading.value = false

      if (res.code != 200) return ClassLoading.setTips('修改个人信息失败！')
      useUserInfoStore().getUserInfo()
      ClassLoading.setTips('修改个人信息成功！')
    }

    // 上传头像文件
    const updateAvatar = async (file: FormData) => {
      const formdata = fetchOriginFile(file, 'file')
      const res = await updateAvatarApi(formdata)
      if (res.code !== 200) return ElMessage.error('上传头像出错！')
      useUserInfoStore().getUserInfo()
    }

    return () => (
      <div class={styles.userinfoContainer}>
        <div class={styles.row}>
          <div class={styles.label}>用户头像：</div>
          <div>
            <el-image
              style="width: 100px; height: 100px;border-radius: 12px"
              fit="cover"
              src={avatar.value}
              preview-src-list={[avatar.value]}
            />
          </div>

          <el-upload
            auto-upload={true}
            before-upload={(file) => updateAvatar(file)}
          >
            <el-button color={buttonColor.value} plain>
              更新头像
            </el-button>
          </el-upload>
        </div>

        <div class={styles.row}>
          <div class={styles.label}>昵称：</div>
          <div class={styles.input}>
            <el-input
              v-model={nickname.value}
              placeholder="Please input you nickname"
            />
          </div>
        </div>

        <div class={styles.row}>
          <div class={styles.label}>描述：</div>
          <div class={styles.input}>
            <el-input
              v-model={description.value}
              type="textarea"
              placeholder="Please input your description"
              maxlength="30"
              show-word-limit
            />
          </div>
        </div>

        <div class={styles.row}>
          <div class={styles.label}>邮箱：</div>
          <div class={styles.input}>
            <el-input
              v-model={email.value}
              placeholder="Please input your E-mail"
            />
          </div>
        </div>

        <div class={styles.row}>
          <div class={styles.label}> </div>
          <div class={styles.btnRow}>
            <el-button
              loading={ClassLoading.loading.value}
              plain
              color={buttonColor.value}
              onClick={updateInfo}
            >
              更新信息
            </el-button>
            <div>{ClassLoading.resultTips.value}</div>
          </div>
        </div>
      </div>
    )
  },
})

//
// 用户密码设置部分
const UserPassword = defineComponent({
  setup() {
    const { buttonColor } = storeToRefs(useThemeStore())

    const oldPassword = ref<string>('')
    const newPassword = ref<string>('')

    const ClassLoading = new LoadingClass()

    // 修改密码
    const modifyPassword = async () => {
      if (!oldPassword.value || !newPassword.value)
        return ClassLoading.setTips('请将参数补充完整！')

      const data = {
        oldPassword: oldPassword.value.trim(),
        newPassword: newPassword.value.trim(),
      }
      ClassLoading.loading.value = true
      const res = await modifyPasswordApi(data)
      ClassLoading.loading.value = false

      if (res.code !== 200) return ClassLoading.setTips('修改密码失败！')
      ClassLoading.setTips('修改密码成功！')
      newPassword.value = ''
      oldPassword.value = ''
    }

    return () => (
      <div class={styles.passwordContainer}>
        <div class={styles.row}>
          <div class={styles.label}>旧密码：</div>
          <div class={styles.input}>
            <el-input
              v-model={oldPassword.value}
              type="password"
              show-password
              placeholder="Please input your old password"
            />
          </div>
        </div>

        <div class={styles.row}>
          <div class={styles.label}>新密码：</div>
          <div class={styles.input}>
            <el-input
              v-model={newPassword.value}
              type="password"
              show-password
              placeholder="Please input your new password"
            />
          </div>
        </div>

        <div class={styles.row}>
          <div class={styles.label}> </div>
          <div class={styles.btnRow}>
            <el-button
              loading={ClassLoading.loading.value}
              plain
              color={buttonColor.value}
              onClick={modifyPassword}
            >
              修改密码
            </el-button>
            <div> {ClassLoading.resultTips.value}</div>
          </div>
        </div>
      </div>
    )
  },
})

//
// 自定义主题部分
const CustomTheme = defineComponent({
  setup() {
    return () => (
      <div>
        <div>自定义主题部分</div>
      </div>
    )
  },
})

//
// 权限控制测试
const AuthorityControl = defineComponent({
  setup() {
    onMounted(() => {
      getRoleList()
      getPermissionsList()
      getUserRoles()
    })

    // 所有的角色列表项
    const allRoleList = ref<roleDetailItf[]>([])
    // 所有权限列表项
    const allPermissionsList = ref<permissionsDetailItf[]>([])

    // 获取角色列表
    const getRoleList = async () => {
      const res = await getRoleListApi()
      if (res.code !== 200) return ElMessage.error('获取角色列表失败！')
      allRoleList.value = res.data
    }

    // 获取权限列表
    const getPermissionsList = async () => {
      const res = await getPermissionsListApi()
      if (res.code !== 200) return ElMessage.error('获取权限列表失败！')
      allPermissionsList.value = res.data
    }

    // 用户所拥有的角色列表
    const userRolesList = ref<roleUserDetailItf[]>([])
    // 下拉框角色选项值
    const selectValue = ref<string[]>([])

    // 获取用户角色列表
    const getUserRoles = async () => {
      const res = await getUserRolesApi()
      if (res.code !== 200) return ElMessage.error('获取用户角色列表失败！')
      userRolesList.value = res.data
      const arr = res.data.map((item) => item.rid)
      selectValue.value = arr
    }

    // 设置用户角色
    const setUserRoles = async () => {
      const res = await setUserRolesApi(selectValue.value)
      if (res.code !== 200) return ElMessage.error('更新用户角色失败！')
      ElMessage.success('更新用户角色成功！')
      getUserRoles()
    }

    // 当前展开的折叠面板项 activeNames
    const currentCollapseItem = ref<string>(null)
    // 折叠面板展开项变化时的回调处理函数
    const collapseChangeHandler = (val: string) =>
      (currentCollapseItem.value = val)

    //
    // 角色权限列表组件
    const PermissionsList = defineComponent({
      props: {
        roleId: { type: String, default: '' },
        activeName: { type: String, default: '' },
        permissionsList: {
          type: Array as () => permissionsDetailItf[],
          default: [],
        },
      },
      setup(props) {
        watch(
          () => props.activeName,
          () => {
            if (props.activeName === props.roleId) getRolePermissionsDetail()
          }
        )

        // 角色拥有的权限详情列表
        const permissionsDetail = ref<rolePermissionsDetailItf[]>([])
        // 获取角色拥有的权限列表详情
        const getRolePermissionsDetail = async () => {
          const res = await getRolePermissionsDetailApi(props.roleId)
          permissionsDetail.value = res.data
        }

        // 角色拥有的权限详情 map，包含未拥有的权限详情
        const permissionsDetailMap = ref<{ [key: string]: number }>({})
        // 设置角色拥有的权限列表详情 map
        const setPermissionsDetailMap = () => {
          if (
            props.permissionsList.length === 0 ||
            permissionsDetail.value.length === 0
          )
            return

          // 将所有的权限详情汇总，权限id作为键，是否拥有作为值
          const map = {}
          permissionsDetail.value.map((item) => (map[item.pid] = true))
          props.permissionsList.map((item) => {
            if (!map[item.id]) map[item.id] = false
          })
          permissionsDetailMap.value = map
        }

        watch(
          () => props.permissionsList,
          () => setPermissionsDetailMap()
        )
        watch(
          () => permissionsDetail.value,
          () => setPermissionsDetailMap()
        )

        // 更新角色拥有的权限
        const setRolePermissions = async () => {
          let arr = []
          props.permissionsList.map((item) => {
            if (permissionsDetailMap.value[item.id]) arr.push(item.id)
          })

          const res = await setRolePermissionsApi(props.roleId, arr)
          if (res.code !== 200) return ElMessage.error('更新角色权限失败')
          ElMessage.success('更新角色权限成功')
          getRolePermissionsDetail()
        }

        return () => (
          <div>
            {props.permissionsList.map((item) => {
              return (
                <el-checkbox
                  key={item.id}
                  label={item.name}
                  v-model={permissionsDetailMap.value[item.id]}
                  size="large"
                />
              )
            })}

            <div
              style={{
                paddingTop: '10px',
                display: 'flex',
                justifyContent: 'flex-end',
              }}
            >
              <el-button type="primary" onClick={setRolePermissions}>
                更新权限
              </el-button>
            </div>
          </div>
        )
      },
    })

    const userDelete = async () => {
      const res = await userDeleteApi()
      if (res.code !== 200) return ElMessage.error(res.message)
      ElMessage.success(res.message)
    }
    const userAdd = async () => {
      const res = await userAddApi()
      if (res.code !== 200) return ElMessage.error(res.message)
      ElMessage.success(res.message)
    }
    const userEdit = async () => {
      const res = await userEditApi()
      if (res.code !== 200) return ElMessage.error(res.message)
      ElMessage.success(res.message)
    }
    const userCheck = async () => {
      const res = await userCheckApi()
      if (res.code !== 200) return ElMessage.error(res.message)
      ElMessage.success(res.message)
    }

    return () => (
      <div class={styles.authorityControlContainer}>
        <div class={styles.selectBar}>
          <el-select
            multiple
            placeholder="Select"
            style="width: 70%"
            v-model={selectValue.value}
          >
            {allRoleList.value.map((item) => {
              return (
                <el-option key={item.id} label={item.name} value={item.id} />
              )
            })}
          </el-select>

          <el-button type="primary" onClick={setUserRoles}>
            更新当前用户角色
          </el-button>
        </div>

        <div class={styles.label}>角色列表</div>

        <el-collapse accordion={true} onChange={collapseChangeHandler}>
          {allRoleList.value.map((item) => {
            return (
              <el-collapse-item
                name={item.id}
                v-slots={{
                  title: () => (
                    <div class={styles.collapseItemTitle}>
                      <div>{item.name} </div>
                      <div>{item.realname} </div>
                      <div>{item.description}</div>
                    </div>
                  ),
                }}
              >
                <PermissionsList
                  roleId={item.id}
                  activeName={currentCollapseItem.value}
                  permissionsList={allPermissionsList.value}
                />
              </el-collapse-item>
            )
          })}
        </el-collapse>

        <div class={styles.requestBtnsBar}>
          <el-button type="primary" onClick={userDelete}>
            userDelete
          </el-button>
          <el-button type="primary" onClick={userAdd}>
            userAdd
          </el-button>
          <el-button type="primary" onClick={userEdit}>
            userEdit
          </el-button>
          <el-button type="primary" onClick={userCheck}>
            userCheck
          </el-button>
        </div>
      </div>
    )
  },
})
</script>

<style lang="less" scoped>
.settingContainer {
  width: calc(100% - 24px);
  min-height: 100%;
  padding: 12px;

  > .optionsBar {
    width: 100%;
    display: flex;
    flex-wrap: wrap;
    margin-bottom: 10px;

    > .option {
      padding: 8px 16px;
      margin-right: 16px;
      margin-bottom: 6px;
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      position: relative;
      cursor: pointer;
      font-weight: bold;
      color: #797974;
      user-select: none;

      &:hover {
        &::after {
          content: '';
          height: 3px;
          width: 80%;
          background-color: var(--theme-hover-label);
          position: absolute;
          bottom: -2px;
        }

        > div {
          scale: 1.1;
        }
      }
    }

    > #currentOption {
      &::after {
        content: '';
        height: 3px;
        width: 80%;
        background-color: var(--theme-active-label);
        position: absolute;
        bottom: -2px;
      }

      > div {
        scale: 1.1;
      }
    }
  }

  > .divide {
    height: 2px;
    width: 100%;
    background-color: var(--theme-header);
  }
}
</style>
